package com.xncoding.async;

import cn.hutool.core.thread.ThreadUtil;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;

public class CompletableFutureTets {
    private static final Logger logger = LoggerFactory.getLogger(AsyncTests.class);

    private ExecutorService executor = Executors.newCachedThreadPool() ;
    @Test
    public void asyncTest() {
        long start = System.currentTimeMillis();
        try {
//            testMethod().get(4000L, TimeUnit.MILLISECONDS);
            testMethod().get();
            logger.info("total time: " + " seconds");
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 耗时时间
        float totalTime = (float)(System.currentTimeMillis() - start) / 1000;
        logger.info("total time: " + totalTime + " seconds");
    }

    @Test
    public void asyncTest2() {
        long start = System.currentTimeMillis();
        CompletableFuture<String> future = testMethod2();
        // 计算结果完成时的回调方法
        try {
            logger.info(" 计算结果完成时的回调方法");
            future.whenComplete((k, v) -> {
                System.out.println("返回k=" + k);
                System.out.println("异常v=" + v);
            }).exceptionally(e -> {
                System.out.println("捕获异常=" + e.getMessage());
                return "okk";
            }).get(4000, TimeUnit.MILLISECONDS);

        } catch (Exception e) {
            e.printStackTrace();
        }
        // 耗时时间
        float totalTime = (float)(System.currentTimeMillis() - start) / 1000;
        logger.info("total time: " + totalTime + " seconds");
    }
    @Test
    public void asyncTest3() throws Exception {
        executor.submit(new Runnable(){
            public void run() {

                try {
                    //要执行的业务代码，我们这里没有写方法，可以让线程休息几秒进行测试
                    Thread.sleep(1000);
                    logger.info("睡够啦~");
                }catch(Exception e) {
                    throw new RuntimeException("报错啦！！");
                }
            }
        });
        logger.info("----");
        Thread.sleep(3000);
    }

    @Test
    public void asyncTest4() throws Exception {
        System.out.println("main函数开始执行");
        ExecutorService executor = Executors.newFixedThreadPool(1);
        Future<Integer> future = executor.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {

                System.out.println("===task start===");
                Thread.sleep(5000);
                System.out.println("===task finish===");
                return 3;
            }
        });

        System.out.println("main函数执行结束");
//这里需要返回值时会阻塞主线程，如果不需要返回值使用是OK的。倒也还能接收
        Integer result=future.get();
//        System.in.read();

    }
    @Test
    public void asyncTest5() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("异步有返回");
            return "ok";
        });;
        while (!completableFuture.isDone()) {
            System.out.println("CompletableFuture is not finished yet...");
        }
        String result = (String) completableFuture.get();
        System.out.println(result);
    }

    @Test
    public void asyncTest6() throws ExecutionException, InterruptedException {
        ExecutorService threadpool = Executors.newCachedThreadPool();
        ListeningExecutorService service = MoreExecutors.listeningDecorator(threadpool);
        ListenableFuture<Long> guavaFuture = (ListenableFuture<Long>) service.submit(()-> System.out.println(111));
         guavaFuture.get();
        System.out.println("11111111111111111");
    }


    // 无返回值的异步方法CompletableFuture.runAsync()
    public CompletableFuture<Void> testMethod() {
        return CompletableFuture.runAsync(() -> {
            ThreadUtil.sleep(3000L);
            System.out.println("异步无返回");
        });
    }

    // 有返回值的异步方法CompletableFuture.supplyAsync()
    public CompletableFuture<String> testMethod2() {
        return CompletableFuture.supplyAsync(() -> {
            ThreadUtil.sleep(3000L);
            System.out.println("异步有返回");
            return "ok";
        });
    }

    public void factorial(int i)  {

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("factorial---"+i);

    }



}
